using System;
using System.Runtime.InteropServices;

namespace Leap
{
	public class Vector : IDisposable
	{
		private HandleRef swigCPtr;

		protected bool swigCMemOwn;

		public float x
		{
			get
			{
				return LeapPINVOKE.Vector_x_get(swigCPtr);
			}
			set
			{
				LeapPINVOKE.Vector_x_set(swigCPtr, value);
			}
		}

		public float y
		{
			get
			{
				return LeapPINVOKE.Vector_y_get(swigCPtr);
			}
			set
			{
				LeapPINVOKE.Vector_y_set(swigCPtr, value);
			}
		}

		public float z
		{
			get
			{
				return LeapPINVOKE.Vector_z_get(swigCPtr);
			}
			set
			{
				LeapPINVOKE.Vector_z_set(swigCPtr, value);
			}
		}

		public float Magnitude => LeapPINVOKE.Vector_Magnitude_get(swigCPtr);

		public float MagnitudeSquared => LeapPINVOKE.Vector_MagnitudeSquared_get(swigCPtr);

		public float Pitch => LeapPINVOKE.Vector_Pitch_get(swigCPtr);

		public float Roll => LeapPINVOKE.Vector_Roll_get(swigCPtr);

		public float Yaw => LeapPINVOKE.Vector_Yaw_get(swigCPtr);

		public Vector Normalized
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Vector_Normalized_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new Vector(intPtr, true);
			}
		}

		public static Vector Zero => new Vector(LeapPINVOKE.Vector_Zero_get(), false);

		public static Vector XAxis => new Vector(LeapPINVOKE.Vector_XAxis_get(), false);

		public static Vector YAxis => new Vector(LeapPINVOKE.Vector_YAxis_get(), false);

		public static Vector ZAxis => new Vector(LeapPINVOKE.Vector_ZAxis_get(), false);

		public static Vector Forward => new Vector(LeapPINVOKE.Vector_Forward_get(), false);

		public static Vector Backward => new Vector(LeapPINVOKE.Vector_Backward_get(), false);

		public static Vector Left => new Vector(LeapPINVOKE.Vector_Left_get(), false);

		public static Vector Right => new Vector(LeapPINVOKE.Vector_Right_get(), false);

		public static Vector Up => new Vector(LeapPINVOKE.Vector_Up_get(), false);

		public static Vector Down => new Vector(LeapPINVOKE.Vector_Down_get(), false);

		public Vector(IntPtr cPtr, bool cMemoryOwn)
		{
			swigCMemOwn = cMemoryOwn;
			swigCPtr = new HandleRef(this, cPtr);
		}

		public static HandleRef getCPtr(Vector obj)
		{
			return obj?.swigCPtr ?? new HandleRef(null, IntPtr.Zero);
		}

		~Vector()
		{
			Dispose();
		}

		public virtual void Dispose()
		{
			lock (this)
			{
				if (swigCPtr.Handle != IntPtr.Zero)
				{
					if (swigCMemOwn)
					{
						swigCMemOwn = false;
						LeapPINVOKE.delete_Vector(swigCPtr);
					}
					swigCPtr = new HandleRef(null, IntPtr.Zero);
				}
				GC.SuppressFinalize(this);
			}
		}

		public static Vector operator +(Vector v1, Vector v2)
		{
			return v1._operator_add(v2);
		}

		public static Vector operator -(Vector v1, Vector v2)
		{
			return v1._operator_sub(v2);
		}

		public static Vector operator *(Vector v1, float scalar)
		{
			return v1._operator_mul(scalar);
		}

		public static Vector operator *(float scalar, Vector v1)
		{
			return v1._operator_mul(scalar);
		}

		public static Vector operator /(Vector v1, float scalar)
		{
			return v1._operator_div(scalar);
		}

		public static Vector operator -(Vector v1)
		{
			return v1._operator_sub();
		}

		public float[] ToFloatArray()
		{
			return new float[3]
			{
				x,
				y,
				z
			};
		}

		public Vector()
			: this(LeapPINVOKE.new_Vector__SWIG_0(), true)
		{
		}

		public Vector(float _x, float _y, float _z)
			: this(LeapPINVOKE.new_Vector__SWIG_1(_x, _y, _z), true)
		{
		}

		public Vector(Vector vector)
			: this(LeapPINVOKE.new_Vector__SWIG_2(getCPtr(vector)), true)
		{
			if (!LeapPINVOKE.SWIGPendingException.Pending)
			{
				return;
			}
			throw LeapPINVOKE.SWIGPendingException.Retrieve();
		}

		public float DistanceTo(Vector other)
		{
			float result = LeapPINVOKE.Vector_DistanceTo(swigCPtr, getCPtr(other));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public float AngleTo(Vector other)
		{
			float result = LeapPINVOKE.Vector_AngleTo(swigCPtr, getCPtr(other));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public float Dot(Vector other)
		{
			float result = LeapPINVOKE.Vector_Dot(swigCPtr, getCPtr(other));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public Vector Cross(Vector other)
		{
			Vector result = new Vector(LeapPINVOKE.Vector_Cross(swigCPtr, getCPtr(other)), true);
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		private Vector _operator_sub()
		{
			return new Vector(LeapPINVOKE.Vector__operator_sub__SWIG_0(swigCPtr), true);
		}

		private Vector _operator_add(Vector other)
		{
			Vector result = new Vector(LeapPINVOKE.Vector__operator_add(swigCPtr, getCPtr(other)), true);
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		private Vector _operator_sub(Vector other)
		{
			Vector result = new Vector(LeapPINVOKE.Vector__operator_sub__SWIG_1(swigCPtr, getCPtr(other)), true);
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		private Vector _operator_mul(float scalar)
		{
			return new Vector(LeapPINVOKE.Vector__operator_mul(swigCPtr, scalar), true);
		}

		private Vector _operator_div(float scalar)
		{
			return new Vector(LeapPINVOKE.Vector__operator_div(swigCPtr, scalar), true);
		}

		public override string ToString()
		{
			return LeapPINVOKE.Vector_ToString(swigCPtr);
		}

		public bool Equals(Vector other)
		{
			bool result = LeapPINVOKE.Vector_Equals(swigCPtr, getCPtr(other));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public bool IsValid()
		{
			return LeapPINVOKE.Vector_IsValid(swigCPtr);
		}

		private float _operator_get(uint index)
		{
			return LeapPINVOKE.Vector__operator_get(swigCPtr, index);
		}
	}
}
